/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = apm4lua_report.c                                              */
/*  NOTE      =                                                               */
/*  DATE      = 2015/09/06 by yaohl                                           */
/******************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <iconv2utf8.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/aes.h>

#if defined(FRLINUX4) || defined(FRLINUX5)
    extern "C"{
    #include <lua.h>
    }
#else
    #ifdef LIB_APM_LUAJIT
    #include <luajit-2.0/lua.hpp>
    #else
    #include <lua.hpp>
    #endif
#endif

#include "frcomm.h"
#include "frlist.h"
#include "frlog.h"
#include "frsutl.h"

#include "frreport_opt.h"

#define  FRLUA_SUCC     0
#define  FRLUA_FAIL     1

/*******************************************************************************
*  FUNC     :  获取MsgType
*  ARGS     :  p_st_report_data          (Frreport_data *)
*  RTN      :  返回message type
*  NOTE     :
*******************************************************************************/
int luaReport_get_messageType(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);

    if(p_st_report_data == NULL)
    {
        lua_pushinteger(p_lua_handle, FRREPORT_TYPE_L7DATA_UNKONWN);
        return 1;
    }

    lua_pushinteger(p_lua_handle, FrReportOpt_get_messageType(p_st_report_data));
    return 1;
}

/*******************************************************************************
*  FUNC     :  获取l4 protocol
*  ARGS     :  p_st_report_data          (Frreport_data *)
*  RTN      :  返回l4 protocol
*  NOTE     :  没有取得时,设置为0
*******************************************************************************/
int luaReport_get_l4proto(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = NULL;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    if(p_st_report_data == NULL)
    {
        lua_pushinteger(p_lua_handle, 0);
        return 1;
    }

    lua_pushinteger(p_lua_handle, FrReportOpt_get_l4proto(p_st_report_data));
    return 1;
}

/*******************************************************************************
*  FUNC     :  获取l7 protocol
*  ARGS     :  p_st_report_data          (Frreport_data *)
*  RTN      :  返回l7 protocol
*  NOTE     :  没有取得时,设置为APM_L7_UNKNOWN
*******************************************************************************/
int luaReport_get_l7proto(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = NULL;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    if(p_st_report_data == NULL)
    {
        lua_pushinteger(p_lua_handle, APM_L7_UNKNOWN);
        return 1;
    }

    lua_pushinteger(p_lua_handle, FrReportOpt_get_l7proto(p_st_report_data));
    return 1;
}

/*******************************************************************************
*  FUNC     :  设置l7 protocol
*  ARGS     :  p_st_report_data          (Frreport_data *)
*           ：  l7_proto                  (int)
*  RTN      :  0(FRLUA_SUCC):成功; 1(FRLUA_FAIL):失败
*  NOTE     :
*******************************************************************************/
int luaReport_set_l7proto(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = NULL;
    int i_l7_proto = 0, i_ret_fun=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    if(p_st_report_data == NULL)
    {
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
        return 1;
    }

    i_l7_proto = lua_tointeger(p_lua_handle, 2);
    if(i_l7_proto < 0)
    {
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
        return 1;
    }

    i_ret_fun = FrReportOpt_set_l7proto(p_st_report_data, i_l7_proto);
    if(i_ret_fun == FR_SUCC)
        lua_pushinteger(p_lua_handle, FRLUA_SUCC);
    else
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
    return 1;
}

/*******************************************************************************
*  FUNC     :  获取src ip
*  ARGS     :  p_st_report_data          (Frreport_data *)
*  RTN      :  返回src ip                 (eg.192.168.18.20)
*  NOTE     :  没有取得时,设置为NULL
*******************************************************************************/
int luaReport_get_srcIp(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = NULL;
    char arr_buff[128];
    u_int ui_ip=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    if(p_st_report_data == NULL)
    {
        lua_pushstring(p_lua_handle, NULL);
        return 1;
    }

    ui_ip = FrReportOpt_get_srcIp(p_st_report_data);
    if(ui_ip == 0)
    {
        lua_pushstring(p_lua_handle, NULL);
        return 1;
    }

    sprintf(arr_buff, "%s", int_ntoa(ui_ip));
    lua_pushstring(p_lua_handle, arr_buff);
    return 1;
}

/*******************************************************************************
*  FUNC     :  获取src port
*  ARGS     :  p_st_report_data          (Frreport_data *)
*  RTN      :  返回src port
*  NOTE     :  没有取得时,设置为0
*******************************************************************************/
int luaReport_get_srcPort(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = NULL;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    if(p_st_report_data == NULL)
    {
        lua_pushinteger(p_lua_handle, 0);
        return 1;
    }

    lua_pushinteger(p_lua_handle, FrReportOpt_get_srcPort(p_st_report_data));
    return 1;
}

/*******************************************************************************
*  FUNC     :  获取dest ip
*  ARGS     :  p_st_report_data          (Frreport_data *)
*  RTN      :  返回dest ip                (eg.192.168.18.21)
*  NOTE     :  没有取得时,设置为NULL
*******************************************************************************/
int luaReport_get_dstIp(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = NULL;
    char arr_buff[128];
    u_int ui_ip=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    if(p_st_report_data == NULL)
    {
        lua_pushstring(p_lua_handle, NULL);
        return 1;
    }

    ui_ip = FrReportOpt_get_dstIp(p_st_report_data);
    if(ui_ip == 0)
    {
        lua_pushstring(p_lua_handle, NULL);
        return 1;
    }

    sprintf(arr_buff, "%s", int_ntoa(ui_ip));
    lua_pushstring(p_lua_handle, arr_buff);
    return 1;
}

/*******************************************************************************
*  FUNC     :  获取dest port
*  ARGS     :  p_st_report_data          (Frreport_data *)
*  RTN      :  返回dest port
*  NOTE     :  没有取得时,设置为0
*******************************************************************************/
int luaReport_get_dstPort(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = NULL;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    if(p_st_report_data == NULL)
    {
        lua_pushinteger(p_lua_handle, 0);
        return 1;
    }

    lua_pushinteger(p_lua_handle, FrReportOpt_get_dstPort(p_st_report_data));
    return 1;
}

/*******************************************************************************
*  FUNC     :  设置src ip
*  ARGS     :  p_st_report_data         (Frreport_data *)
*           :  p_src_ip                 (eg.192.168.18.20)
*  RTN      :  0(FRLUA_SUCC):成功; 1(FRLUA_FAIL):失败
*  NOTE     :
*******************************************************************************/
int luaReport_set_srcIp(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = NULL;
    const char *p_src_ip=NULL;
    int i_ret_fun=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    p_src_ip = lua_tostring(p_lua_handle, 2);
    if(p_st_report_data == NULL
       || p_src_ip == NULL || *p_src_ip == '\0')
    {
        FRLOG_WARN_DETAIL("input parameter err");
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
        return 1;
    }

    i_ret_fun = FrReportOpt_set_srcIp(p_st_report_data, p_src_ip);
    if(i_ret_fun == FR_SUCC)
        lua_pushinteger(p_lua_handle, FRLUA_SUCC);
    else
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
    return 1;
}

/*******************************************************************************
*  FUNC     :  设置src port
*  ARGS     :  p_st_report_data          (Frreport_data *)
*           ：  p_src_port                (u_short)
*  RTN      :  0(FRLUA_SUCC):成功; 1(FRLUA_FAIL):失败
*  NOTE     :
*******************************************************************************/
int luaReport_set_srcPort(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = NULL;
    int i_port=0;
    int i_ret_fun=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    i_port = lua_tointeger(p_lua_handle, 2);
    if(p_st_report_data == NULL)
    {
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
        return 1;
    }

    i_ret_fun = FrReportOpt_set_srcPort(p_st_report_data, i_port);
    if(i_ret_fun == FR_SUCC)
        lua_pushinteger(p_lua_handle, FRLUA_SUCC);
    else
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
    return 1;
}

/*******************************************************************************
*  FUNC     :  设置dst ip
*  ARGS     :  p_st_report_data         (Frreport_data *)
*           :  p_dst_ip                 (eg.192.168.18.20)
*  RTN      :  0(FRLUA_SUCC):成功; 1(FRLUA_FAIL):失败
*  NOTE     :
*******************************************************************************/
int luaReport_set_dstIp(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = NULL;
    const char *p_dst_ip=NULL;
    int i_ret_fun=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    p_dst_ip = lua_tostring(p_lua_handle, 2);
    if(p_st_report_data == NULL
       || p_dst_ip == NULL || *p_dst_ip == '\0')
    {
        FRLOG_WARN_DETAIL("input parameter err");
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
        return 1;
    }

    i_ret_fun = FrReportOpt_set_dstIp(p_st_report_data, p_dst_ip);
    if(i_ret_fun == FR_SUCC)
        lua_pushinteger(p_lua_handle, FRLUA_SUCC);
    else
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
    return 1;
}

/*******************************************************************************
*  FUNC     :  设置dest port
*  ARGS     :  p_st_report_data          (Frreport_data *)
*           ：  p_dst_port                (u_short)
*  RTN      :  0(FRLUA_SUCC):成功; 1(FRLUA_FAIL):失败
*  NOTE     :
*******************************************************************************/
int luaReport_set_dstPort(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data = NULL;
    int i_port=0;
    int i_ret_fun=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    i_port = lua_tointeger(p_lua_handle, 2);
    if(p_st_report_data == NULL)
    {
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
        return 1;
    }

    i_ret_fun = FrReportOpt_set_dstPort(p_st_report_data, i_port);
    if(i_ret_fun == FR_SUCC)
        lua_pushinteger(p_lua_handle, FRLUA_SUCC);
    else
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
    return 1;
}

/*******************************************************************************
*  FUNC     :  获取指定数据大小
*  ARGS     :  p_st_report_data         (Frreport_data *)
*           :  p_key                    (字段名 char*)
*  RTN      :  指定字段的个数
*  NOTE     :  出错返回0
*******************************************************************************/
int luaReport_get_fieldSize(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data=NULL;
    const char *p_key = NULL;
    int i_count = 0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    p_key = lua_tostring(p_lua_handle, 2);
    if(p_st_report_data == NULL
       || p_key == NULL || *p_key == '\0')
    {
        lua_pushinteger(p_lua_handle, 0);
        return 1;
    }

    i_count = FrReportOpt_get_fieldSize(p_st_report_data, p_key);
    lua_pushinteger(p_lua_handle, i_count);
    return 1;
}

/*******************************************************************************
*  FUNC     :  判断某个指定key是否存在
*  ARGS     :  p_st_report_data         (Frreport_data *)
*           :  p_key                    (字段名 char*)
*  RTN      :  true(1):存在 false(0):不存在/出错
*  NOTE     :  出错返回 false
*******************************************************************************/
int luaReport_get_existsField(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data=NULL;
    const char *p_key = NULL;
    int i_exists = 0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    p_key = lua_tostring(p_lua_handle, 2);
    if(p_st_report_data == NULL || p_st_report_data->em_type != FRREPORT_TYPE_L7DATA
       || p_key == NULL || *p_key == '\0')
    {
        lua_pushboolean(p_lua_handle, 0);
        return 1;
    }

    i_exists = FrReportOpt_get_existsField(p_st_report_data, p_key);
    lua_pushboolean(p_lua_handle, i_exists);
    return 1;
}

/*******************************************************************************
*  FUNC     :  获取解析数据
*  ARGS     :  p_st_report_data         (Frreport_data *)
*           :  p_key                    (字段名 char*)
*           :  i_index                  (表示数组下标，从0开始)
*  RTN      :  指定字段名的内容
*  NOTE     :
*******************************************************************************/
int luaReport_get_field(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data=NULL;
    const char *p_key = NULL;
    int i_index = 0;
    Frvar_field *p_st_field=NULL;
    char arr_buff[64];

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    p_key = lua_tostring(p_lua_handle, 2);
    i_index = lua_tointeger(p_lua_handle, 3);
    if(p_st_report_data == NULL || p_st_report_data->em_type != FRREPORT_TYPE_L7DATA
       || p_key == NULL || *p_key == '\0')
    {
        lua_pushstring(p_lua_handle, NULL);
        return 1;
    }

    p_st_field = FrReportOpt_get_field(p_st_report_data, p_key, i_index);
    if(p_st_field == NULL)
    {
        lua_pushstring(p_lua_handle, NULL);
        return 1;
    }

    switch(p_st_field->em_data_type)
    {
        case FRLONG:
            snprintf(arr_buff, sizeof(arr_buff), "%lld", p_st_field->field_value.ll_value);
            lua_pushstring(p_lua_handle, arr_buff);
            break;
        case FRFLOAT:
        case FRDOUBLE:
            snprintf(arr_buff, sizeof(arr_buff), "%f", p_st_field->field_value.f_value);
            lua_pushstring(p_lua_handle, arr_buff);
            break;
        case FRSTRING:
            lua_pushstring(p_lua_handle, p_st_field->field_value.p_value);
            break;
        case FRBLOB:
        case FRCLOB:
            lua_pushlstring(p_lua_handle, p_st_field->field_value.p_st_value->p_data, p_st_field->field_value.p_st_value->ui_len);
            break;
        default:
            lua_pushstring(p_lua_handle, NULL);
    }
    return 1;
}

/*******************************************************************************
*  FUNC     :  加入解析数据
*  ARGS     :  p_st_report_data         (Frreport_data *)
*           :  p_key                    (字段名 const char*)
*           :  p_value                  (解析数据 const char*)
*  RTN      :  0(FRLUA_SUCC):成功; 1(FRLUA_FAIL):失败
*  NOTE     :
*******************************************************************************/
int luaReport_add_fieldStr(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data=NULL;
    const char *p_key = NULL;
    const char *p_value = NULL;
    int i_ret_fun=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    p_key = lua_tostring(p_lua_handle, 2);
    p_value = lua_tostring(p_lua_handle, 3);

    if(p_st_report_data == NULL
       || p_key == NULL || *p_key == '\0')
    {
        FRLOG_WARN_DETAIL("input parameter err");
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
        return 1;
    }

    i_ret_fun = FrReportOpt_add_fieldStr(p_st_report_data, p_key, p_value);
    if(i_ret_fun == FR_FAIL)
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
    else
        lua_pushinteger(p_lua_handle, FRLUA_SUCC);
    return 1;
}

/*******************************************************************************
*  FUNC     :  加入解析数据
*  ARGS     :  p_st_report_data         (Frreport_data *)
*           :  p_key                    (字段名 const char*)
*           :  i_value                  (解析数据 int)
*  RTN      :  0(FRLUA_SUCC):成功; 1(FRLUA_FAIL):失败
*  NOTE     :
*******************************************************************************/
int luaReport_add_fieldLong(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data=NULL;
    const char *p_key = NULL;
    int i_ret_fun=0, i_value=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    p_key = lua_tostring(p_lua_handle, 2);
    i_value = lua_tointeger(p_lua_handle, 3);

    if(p_st_report_data == NULL
       || p_key == NULL || *p_key == '\0')
    {
        FRLOG_WARN_DETAIL("input parameter err");
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
        return 1;
    }

    i_ret_fun = FrReportOpt_add_fieldLong(p_st_report_data, p_key, i_value);
    if(i_ret_fun == FR_FAIL)
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
    else
        lua_pushinteger(p_lua_handle, FRLUA_SUCC);
    return 1;
}

/*******************************************************************************
*  FUNC     :  加入解析数据
*  ARGS     :  p_st_report_data         (Frreport_data *)
*           :  p_key                    (字段名 const char*)
*           :  d_value                  (解析数据 double)
*  RTN      :  0(FRLUA_SUCC):成功; 1(FRLUA_FAIL):失败
*  NOTE     :
*******************************************************************************/
int luaReport_add_fieldDouble(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data=NULL;
    const char *p_key = NULL;
    int i_ret_fun=0;
    double d_value=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    p_key = lua_tostring(p_lua_handle, 2);
    d_value = lua_tonumber(p_lua_handle, 3);

    if(p_st_report_data == NULL
       || p_key == NULL || *p_key == '\0')
    {
        FRLOG_WARN_DETAIL("input parameter err");
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
        return 1;
    }

    i_ret_fun = FrReportOpt_add_fieldDouble(p_st_report_data, p_key, d_value);
    if(i_ret_fun == FR_FAIL)
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
    else
        lua_pushinteger(p_lua_handle, FRLUA_SUCC);
    return 1;
}

/*******************************************************************************
*  FUNC     :  删除所有相同节点名
*  ARGS     :  p_st_report_data         (Frreport_data *)
*           :  p_key                    (字段名 const char*)
*  RTN      :  0(FRLUA_SUCC):成功; 1(FRLUA_FAIL):失败
*  NOTE     :
*******************************************************************************/
int luaReport_del_fieldAll(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data=NULL;
    const char *p_key = NULL;
    int i_ret_fun=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    p_key = lua_tostring(p_lua_handle, 2);
    if(p_st_report_data == NULL
       || p_key == NULL || *p_key == '\0')
    {
        FRLOG_WARN_DETAIL("input parameter err");
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
        return 1;
    }

    i_ret_fun = FrReportOpt_del_fieldAll(p_st_report_data, p_key);
    if(i_ret_fun == FR_FAIL)
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
    else
        lua_pushinteger(p_lua_handle, FRLUA_SUCC);
    return 1;
}

/*******************************************************************************
*  FUNC     :  l7data里删除指定节点名的第ui_index个
*  ARGS     :  p_st_report_data         (Frreport_data *)
*           :  p_key                    (字段名 const char*)
*           :  i_index                  (从0开始)
*  RTN      :  0(FRLUA_SUCC):成功; 1(FRLUA_FAIL):失败
*  NOTE     :
*******************************************************************************/
int luaReport_del_fieldIndex(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data=NULL;
    const char *p_key = NULL;
    int i_ret_fun=0, i_index=0;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    p_key = lua_tostring(p_lua_handle, 2);
    i_index = lua_tointeger(p_lua_handle, 3);
    if(p_st_report_data == NULL
       || p_key == NULL || *p_key == '\0' || i_index < 0)
    {
        FRLOG_WARN_DETAIL("input parameter err");
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
        return 1;
    }

    i_ret_fun = FrReportOpt_del_fieldIndex(p_st_report_data, p_key, i_index);
    if(i_ret_fun == FR_FAIL)
        lua_pushinteger(p_lua_handle, FRLUA_FAIL);
    else
        lua_pushinteger(p_lua_handle, FRLUA_SUCC);
    return 1;
}


/*******************************************************************************
*  FUNC     :  l7data里删除指定节点名的第ui_index个
*  ARGS     :  p_st_report_data         (Frreport_data *)
*           :  i_flag_style             (0:无格式化输出; 其它:格式化输出)
*  RTN      :  数据:成功; NULL:失败
*  NOTE     :
*******************************************************************************/
int luaReport_dumpField(lua_State *p_lua_handle)
{
    Frreport_data *p_st_report_data=NULL;
    int i_flag_style=0;
    char *p_msg=NULL;

    p_st_report_data = (Frreport_data *)lua_touserdata(p_lua_handle, 1);
    i_flag_style = lua_tointeger(p_lua_handle, 2);
    if(p_st_report_data == NULL)
    {
        FRLOG_WARN_DETAIL("input parameter err");
        lua_pushstring(p_lua_handle, NULL);
        return 1;
    }

    if(i_flag_style)
        p_msg = FrReportOpt_dumpField(p_st_report_data, FR_YES);
    else
        p_msg = FrReportOpt_dumpField(p_st_report_data, FR_NO);

    if(p_msg)
        lua_pushstring(p_lua_handle, p_msg);
    else
        lua_pushstring(p_lua_handle, NULL);

    if(p_msg)
        frfree(p_msg);
    return 1;
}

/*******************************************************************************
*  FUNC     :  获取当前系统微秒时间
*  ARGS     :
*  RTN      :  数据:成功; NULL:失败
*  NOTE     :
*******************************************************************************/
int luaReport_get_microsecond(lua_State *p_lua_handle)
{
    struct timeval tv;
    gettimeofday(&tv,NULL);
    long microsecond = tv.tv_sec*1000000+tv.tv_usec;
    lua_pushnumber(p_lua_handle, microsecond);
    return 1;
}

/*******************************************************************************
*  FUNC     :  获取当前系统毫秒时间
*  ARGS     :
*  RTN      :  数据:成功; NULL:失败
*  NOTE     :
*******************************************************************************/
int luaReport_get_millisecond(lua_State *p_lua_handle) {
    struct timeval tv;
    gettimeofday(&tv,NULL);
    long millisecond = (tv.tv_sec*1000000+tv.tv_usec)/1000;
    lua_pushnumber(p_lua_handle, millisecond);
    return 1;
}


/*******************************************************************************
*  FUNC     :  字符串转UTF8格式
*  ARGS     :  p_orig_str                 (原字符串)
*           :  p_charset                  (编码格式)
*  RTN      :  0(FRLUA_SUCC):成功; 1(FRLUA_FAIL):失败
*  NOTE     :
*******************************************************************************/
int luaReport_str_to_utf8(lua_State *p_lua_handle)
{
    char *p_orig_str = NULL;
    unsigned int ui_orig_str_len = 0;
    const char *p_charset = NULL;
    char *p_utf8_str = NULL;
    unsigned int ui_utf8_str_len = 0;

    p_orig_str = (char *) lua_tostring(p_lua_handle, 1);
    p_charset = lua_tostring(p_lua_handle, 2);
    if (p_orig_str == NULL || *p_orig_str == '\0' || p_charset == NULL || *p_charset == '\0')
    {
        FRLOG_WARN_DETAIL("input parameter err");
        lua_pushstring(p_lua_handle, NULL);
        return 1;
    }

    ui_orig_str_len = (unsigned int) strlen(p_orig_str);

    if (iconv_to_utf8(p_orig_str, ui_orig_str_len, p_charset, &p_utf8_str, &ui_utf8_str_len) == FR_SUCC)
        lua_pushstring(p_lua_handle, p_utf8_str);
    else
        lua_pushstring(p_lua_handle, NULL);
    return 1;
}


/*******************************************************************************
*  FUNC     :  读取RSA私钥
*  ARGS     :  p_key_string                 (原字符串)
*  RTN      :  有数据:成功; NULL:失败
*  NOTE     :
*******************************************************************************/
int luaReport_PEM_read_bio_RSAPrivateKey(lua_State *p_lua_handle)
{
    RSA *p_rsa = NULL;
    char *p_key_string = (char *) lua_tostring(p_lua_handle, 1);

    BIO *bio = BIO_new(BIO_s_mem());
    BIO_write(bio, p_key_string, strlen(p_key_string));
    if ((p_rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL)) == NULL)
    {
        BIO_free(bio);
        lua_pushnil(p_lua_handle);
        return 1;
    }
    BIO_free(bio);

    lua_pushlightuserdata(p_lua_handle, (void *) p_rsa);

    return 1;
}

/*******************************************************************************
*  FUNC     :  RSA解密
*  ARGS     :  p_encrypted                (密文)
*           :  p_rsa                      (RSA对象)
*  RTN      :  有数据:成功; NULL:失败
*  NOTE     :
*******************************************************************************/
int luaReport_RSA_private_decrypt(lua_State *p_lua_handle)
{
    char *p_encrypted = NULL;
    char *p_decrypted = NULL;
    RSA *p_rsa = NULL;
    int rsa_len;

    p_encrypted = (char *) lua_tostring(p_lua_handle, 1);
    if (p_encrypted == NULL || p_encrypted[0] == '\0')
    {
        lua_pushnil(p_lua_handle);
        return 1;
    }

    p_rsa = (RSA *) lua_touserdata(p_lua_handle, 2);
    if (p_rsa == NULL)
    {
        lua_pushnil(p_lua_handle);
        return 1;
    }
    rsa_len = RSA_size(p_rsa);
    p_decrypted = (char *) frmalloc(rsa_len + 1);
    memset(p_decrypted, 0, rsa_len + 1);
    if (RSA_private_decrypt(rsa_len, (unsigned char *) p_encrypted, (unsigned char *) p_decrypted, p_rsa, RSA_PKCS1_PADDING) < 0)
    {
        frfree(p_decrypted);
        lua_pushnil(p_lua_handle);
        return 1;
    }
    lua_pushstring(p_lua_handle, p_decrypted);
    frfree(p_decrypted);

    return 1;
}

/*******************************************************************************
*  FUNC     :  AES-CBC解密
*  ARGS     :  p_encrypted                (密文)
*           :  i_encrypted_len            (密文长度)
*           :  p_key                      (密钥)
*           :  p_iv                       (16位初始向量)
*           :  i_bits                     (密钥位数)
*  RTN      :  有数据:成功; NULL:失败
*  NOTE     :
*******************************************************************************/
int luaReport_AES_cbc_encrypt(lua_State *p_lua_handle)
{
    char *p_encrypted = NULL;
    int i_encrypted_len = 0;
    char *p_decrypted = NULL;
    char *p_key = NULL;
    char *p_iv = NULL;
    AES_KEY aes;

    // 密文
    p_encrypted = (char *) lua_tostring(p_lua_handle, 1);
    if (p_encrypted == NULL || p_encrypted[0] == '\0')
    {
        lua_pushstring(p_lua_handle, NULL);
        return 1;
    }

    // 密文长度
    i_encrypted_len = (int) lua_tonumber(p_lua_handle, 2);
    if (i_encrypted_len <= 0)
    {
        lua_pushstring(p_lua_handle, NULL);
        return 1;
    }

    // 密钥
    p_key = (char *) lua_tostring(p_lua_handle, 3);
    // 16位初始向量
    p_iv = (char *) lua_tostring(p_lua_handle, 4);
    // 密钥位数
    int i_bits = (int) lua_tonumber(p_lua_handle, 5);

    // 每次执行AES_cbc_encrypt后，iv（向量）会被更新，所以这里要重新拷贝一份
    char *p_iv2 = frstrdup(p_iv);

    if (AES_set_decrypt_key((unsigned char *) p_key, i_bits, &aes) < 0)
    {
        lua_pushnil(p_lua_handle);
        return 1;
    }

    if ((p_decrypted = (char *) frmalloc(sizeof(char) * i_encrypted_len + 1)) == NULL)
    {
        lua_pushnil(p_lua_handle);
        return 1;
    }
    memset(p_decrypted, 0, i_encrypted_len + 1);

    AES_cbc_encrypt((unsigned char *) p_encrypted, (unsigned char *) p_decrypted, i_encrypted_len, &aes, (unsigned char *) p_iv2, AES_DECRYPT);
    frfree(p_iv2);
    p_decrypted[i_encrypted_len] = '\0';
    lua_pushstring(p_lua_handle, p_decrypted);
    frfree(p_decrypted);

    return 1;
}
